import org.devops.Constants


def call(Map map) {
    String VALUES_URL = Constants.VALUES_URL
    String HARBOR_PROJECT = Constants.HARBOR_PROJECT
    String JENKINS_DOCKERFILES_DIR = Constants.JENKINS_DOCKERFILES_DIR
    String GIT_CREDENTIAL_ID = Constants.GIT_CREDENTIAL_ID
    String VERSION = Constants.VERSION
    String BRANCH_FILTER = Constants.DEFAULT_BRANCH_FILTER
    if (map.get("P_ENV") == "prod") {
        BRANCH_FILTER = map.get("PROD_BRANCH_FILTER") ?: Constants.PROD_BRANCH_FILTER
    }

    def COMPILE_COMMAND = map.get("COMPILE_COMMAND")
    def IPS = map.get("IPS")
    def ARCHIVES = map.get("ARCHIVES")
    def ARCHIVE = map.get("ARCHIVE")
    def DEPLOY_DEST = ""
    def REMOTE_COMMAND = map.get("REMOTE_COMMAND")
    def IPS_STR = IPS.join(",")

    pipeline {
        agent any
        environment {
            //必填项
            GIT_URL = map.get("GIT_URL")
            ENV = map.get("P_ENV")
            SERVICE = map.get("P_SERVICE")
        }
        parameters {
            extendedChoice(defaultValue: IPS_STR, description: '部署服务器', multiSelectDelimiter: ',', name: 'DEPLOY_IPS', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', value: IPS_STR, visibleItemCount: 5)
            gitParameter(branch: '', branchFilter: BRANCH_FILTER, defaultValue: 'origin/master', description: '分支', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE', tagFilter: '*', type: 'GitParameterDefinition', useRepository: map.GIT_URL)
            choice(choices: ['deploy', 'rollback','init'], description: '模式', name: 'MOD')
        }
        options {
            timestamps() // 输出构建日志打印时间信息
            timeout(time: 60, unit: 'MINUTES') // 设置构建超时时间
            buildDiscarder(logRotator(numToKeepStr: '5')) // 设置历史构建保留次数
        }
        stages {
            stage('git clone') {
                steps {
                    script {
                        String branch = "$BRANCH".replaceAll("origin/", "")
                        git branch: "${branch}", credentialsId: "${GIT_CREDENTIAL_ID}", url: "${GIT_URL}"
                    }
                }
            }
            stage('编译') {
                when {
                    environment name: 'MOD', value: 'deploy'
                }
                steps {
                    script {
                        for (command in COMPILE_COMMAND) {
                            sh "${command}"
                        }
                    }
                }
            }
            stage('上传,部署') {
                when {
                    environment name: 'MOD', value: 'deploy'
                }
                steps {
                    script {
                        def deployIps = "${params.DEPLOY_IPS}"
                        if (deployIps.size() == 0) {
                            error "请选择要部署的服务器"
                        }

                        //通过ips判断要上传到哪
                        Map ipMap = processIpMap(IPS)
                        def ansibleNames = ipMap.keySet()

                        String branch = "$BRANCH".replaceAll("origin/", "").replaceAll("_", "-").replaceAll("/", "-")
                        String commit = sh(returnStdout: true, script: "git rev-parse --short HEAD").trim()
                        String msg = sh(returnStdout: true, script: "git log --pretty=format:%s ${commit} -1").trim()

                        String remoteDir = sh(returnStdout: true, script: "date +%Y%m%d%H%M%S").trim()
                        def curls = []

                        for (archive in ARCHIVES) {
                            //上传到ansible服务器
                            def fullPath = "/data/app_repos/${ENV}/${SERVICE}/${archive.app}/${remoteDir}"
                            for (ansibleName in ansibleNames) {
                                remoteExec(ansibleName, "mkdir -p ${fullPath}")
                                exeSshPublisher(ansibleName, "", archive.file, fullPath, true)
                            }
                            curls += ["curl -XPOST -H'Content-Type: application/json' http://172.30.11.30:8001/projectInfo/add -d '{\"env\":\"${ENV}\",\"service\": \"${SERVICE}\",\"app\": \"${archive.app}\",\"dir\": \"${remoteDir}\",\"file_name\": \"${archive.file}\",\"exe_type\": \"node\",\"branch\": \"${branch}\",\"commit\": \"${commit}\",\"msg\":\"${msg}\"}'"]
                        }

                        //执行上传,启动命令
                        //REMOTE_COMMAND需要拼接上ip信息
                        for (e in ipMap.entrySet()) {
                            //1.ansible copy
                            def commands = []
                            for (ip in e.getValue()) {
                                if (!deployIps.contains(ip)) {
                                    continue
                                }
                                for (archive in ARCHIVES) {
                                    String fileName = archive.file.split("/").last()
                                    String src = "/data/app_repos/${ENV}/${SERVICE}/${archive.app}/${remoteDir}/${fileName}"
                                    String copy = """ansible ${ip} -m copy -a \"src=${src} dest=${archive.dest}\""""
                                    commands += copy
                                }
                                String startSh = "ansible ${ip} -m shell -a \"${REMOTE_COMMAND}\""
                                commands += startSh
                            }

                            if (commands.size() > 0) {
                                String allCommand = commands.join("\r\n")
                                //2.ansible 执行copy,启动命令
                                echo "命令: ${allCommand}"
                                remoteExec(e.getKey(), allCommand)
                            }
                        }

                        //执行curls
                        def deleteCommands = []
                        for (c in curls) {
                            echo "${c}"
                            String result = sh(returnStdout: true, script: "${c}").trim()
                            def resultJson = readJSON(text: result)
                            def data = resultJson.data
                            if (data.dir != "") {
                                def deleteFile = "/data/app_repos/${data.env}/${data.service}/${data.app}/${data.dir}"
                                echo "删除文件: $deleteFile"
                                deleteCommands += "rm -rf ${deleteFile}"
                            }
                        }

                        String deleteCommand = deleteCommands.join("\r\n")
                        for (ansibleName in ansibleNames) {
                            remoteExec(ansibleName, "${deleteCommand}")
                        }
                    }
                }
            }
            stage("回滚") {
                when {
                    environment name: 'MOD', value: 'rollback'
                }
                steps {
                    script {
                        echo "该job暂不支持回滚!"
                    }
                }
            }
        }
    }
}

def processIpMap(IPS) {
    def internal_ansible = []
    def internet_ansible = []
    Map ipMap = [:]
    for (String ip in IPS) {
        if (ip.startsWith("172.25")) {
            internal_ansible.add(ip)
        } else if (ip.startsWith("172.30")) {
            internet_ansible.add(ip)
        }
    }

    if (internal_ansible.size() > 0) {
        ipMap.put("internal_ansible", internal_ansible)
    }

    if (internet_ansible.size() > 0) {
        ipMap.put("internet_ansible", internet_ansible)
    }

    return ipMap
}

def exeSshPublisher(configName, execCommand, sourceFiles, remoteDirectory, flatten) {
    sshPublisher(publishers: [sshPublisherDesc(configName: configName, transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: execCommand, execTimeout: 120000, flatten: flatten, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: remoteDirectory, remoteDirectorySDF: false, removePrefix: '', sourceFiles: sourceFiles)], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}

def remoteExec(configName, execCommand) {
    exeSshPublisher(configName, execCommand, '', '', false)
}
